#ifndef MCIRC_H
#define MCIRC_H

#include "mconfig.h"
#ifdef GUI_APPLICATION

#include "geometry/mpoint.h"

class MBorderCircPrivate;

class MCirc
{
	public:
		inline MCirc() :
			_center(), _radius(3) {}

		inline MCirc(const MPoint &point, int radius) :
			_center(point), _radius(radius) {}

		inline MCirc(int x, int y, int radius) :
			_center(x, y), _radius(radius) {}

		inline MCirc(const MCirc &other) :
			_center(other._center), _radius(other._radius) {}

	public:
		inline int x() const { return _center.x(); }
		inline int y() const { return _center.y(); }
		inline const MPoint &center() const { return _center; }

		int radius() const { return _radius; }
		int area() const;

		inline bool isValid() const { return _radius >= 0; }
		inline bool isNull() const { return _radius == 0; }

	public:
		inline void setX(int x) { _center.setX(x); }
		inline void setY(int y) { _center.setY(y); }
		inline void move(int x, int y) { _center.move(x, y); }
		inline void move(const MPoint &center) { _center.move(center); }
		bool resize(int radius);

	public:
		bool isInclude(const MCirc &other) const;
		bool isBeIncluded(const MCirc &other) const;

		bool isCutIn(const MCirc &other) const;
		bool isBeCutIn(const MCirc &other) const;
		bool isCutOutsideOn(const MCirc &other) const;

	public:
		const MCirc &operator=(const MCirc &other);
		bool operator&(const MCirc &other) const;

		inline bool operator==(const MCirc &other) const
		{ return _center == other._center and _radius == other._radius; }

		inline bool operator!=(const MCirc &other) const
		{ return _center != other._center and _radius != other._radius; }

	public:
		inline bool operator>(const MCirc &other) const
		{ return area() > other.area(); }

		inline bool operator>=(const MCirc &other) const
		{ return area() >= other.area(); }

		inline bool operator<(const MCirc &other) const
		{ return area() <= other.area(); }

		inline bool operator<=(const MCirc &other) const
		{ return area() <= other.area(); }

	private:
		MPoint _center;
		int _radius;
};

class MBorderCirc
{
	public:
		inline MBorderCirc() :
			circ(), border_width(1) {}

		inline MBorderCirc(const MPoint &point, int radius, int border_width = 1) :
			circ(point, radius), border_width(border_width) {}

		inline MBorderCirc(int x, int y, int radius, int border_width = 1) :
			circ(x, y, radius), border_width(border_width) {}

		inline MBorderCirc(const MCirc &other, int border_width = 1) :
			circ(other), border_width(border_width) {}

		inline MBorderCirc(const MBorderCirc &other) :
			circ(other.circ), border_width(other.border_width) {}

	public:
		inline int x() const { return circ.x(); }
		inline int y() const { return circ.y(); }
		inline const MPoint &center() const { return circ.center(); }

		inline int externalRadius() const { return circ.radius(); }
		inline int borderWidth() const { return border_width; }

		inline MCirc insideCirc() const
		{ return MCirc(circ.center(), circ.radius()-(border_width<<1)); }

		inline int totalArea() const { return circ.area(); }
		inline int insideArea() const { return insideCirc().area(); }

		inline bool isValid() const
		{ return circ.isValid() and border_width >= 0; }

		inline bool isNull() const
		{ return circ.isNull() or border_width == 0; }

	public:
		inline void setX(int x) { circ.setX(x); }
		inline void setY(int y) { circ.setY(y); }
		inline void move(int x, int y) { circ.move(x, y); }
		inline void move(const MPoint &center) { circ.move(center); }

		inline bool resize(int radius) { return circ.resize(radius); }
		bool resize(int radius, int border_width);
		bool setBorderWidth(int border_width);

	public:
		inline bool isInclude(const MCirc &circ) const
		{ return circ.isInclude(circ); }

		inline bool isBeIncluded(const MCirc &circ) const
		{ return circ.isBeIncluded(circ); }

		inline bool isCutIn(const MCirc &circ) const
		{ return circ.isCutIn(circ); }

		inline bool isBeCutIn(const MCirc &circ) const
		{ return circ.isBeCutIn(circ); }

		inline bool isCutOutsideOn(const MCirc &circ) const
		{ return circ.isCutOutsideOn(circ); }

		inline bool isInclude(const MBorderCirc &other) const
		{ return circ.isCutOutsideOn(other.circ); }

		inline bool isBeIncluded(const MBorderCirc &other) const
		{ return circ.isBeIncluded(other.circ); }

		inline bool isCutIn(const MBorderCirc &other) const
		{ return circ.isCutIn(other.circ); }

		inline bool isBeCutIn(const MBorderCirc &other) const
		{ return circ.isBeCutIn(other.circ); }

		inline bool isCutOutsideOn(const MBorderCirc &other) const
		{ return circ.isCutOutsideOn(other.circ); }

	public:
		const MBorderCirc &operator=(const MBorderCirc &other);

		inline bool operator&(const MCirc &other) const
		{ return circ & other; }

		inline bool operator&(const MBorderCirc &other) const
		{ return circ & other.circ; }

		inline bool operator==(const MBorderCirc &other) const
		{ return circ == other.circ and border_width == other.border_width; }

		inline bool operator!=(const MBorderCirc &other) const
		{ return circ != other.circ or border_width != other.border_width; }

	private:
		MCirc circ;
		int border_width;
};


#endif //GUI_APPLICATION

#endif //MCIRC_H
